#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <netdb.h>
#include <netinet/in.h>

#include <poll.h>

#define SERVPORT 3333
#define MAXDATASIZE 100

int main(int argc,char *argv[]) {
    int sockfd, sendbytes;
    char buf[MAXDATASIZE];
    struct hostent* host;
    struct sockaddr_in serv_addr;
	char send_line[MAXDATASIZE], recv_line[MAXDATASIZE];


    if(argc < 2) {
        fprintf(stderr, "Please enter the server's hostname");
        exit(1);
    }

    if((host = gethostbyname(argv[1])) == NULL) { //转换为hostent
        perror("gethostbyname");
        exit(1);
    }
	
    if((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
        perror("创建 client socket 失败");
        exit(1);
    }
	
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(SERVPORT);
    serv_addr.sin_addr = *((struct in_addr *)host->h_addr);
	
    if((connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr))) == -1) {
        perror("connect error");
        exit(1);
    }	
	
	// 初始化长度为 2 的 pollfd 数组  
	struct pollfd event_set[2]; 
	// 设置标准输入的可读事件
	event_set[0].fd = STDIN_FILENO;    
	event_set[0].events = POLLIN;
	// 设置客户端连接 socket 的可读事件
	event_set[1].fd = sockfd; 
    event_set[1].events = POLLIN;
	
	int retval;
	for (;;) {
		// 注册感兴趣的 IO 事件
        retval = poll(event_set, 2, -1);

        if (retval < 0)
            perror("poll()");
		// 判断标准输入是否发生可读事件
		if (event_set[0].revents & POLLIN) {
			if (fgets(send_line, MAXDATASIZE, stdin) != NULL) {
            	if (!strcmp(send_line, "quit\n")) {
                	break;
            	}
				int i = strlen(send_line);
            	if (send_line[i - 1] == '\n') {
                	send_line[i - 1] = 0;
            	}
            	printf("sending '%s'\n", send_line);
            	size_t rt = write(sockfd, send_line, strlen(send_line));
            	if (rt < 0) {
                	perror("write failed");
            	}
            	printf("sended bytes: %zu \n", rt);
        	}
		}
		// 判断客户端连接 socket 是否有可读事件
		if (event_set[1].revents & POLLIN) {
			int n = read(sockfd, recv_line, MAXDATASIZE);
        	if (n < 0) {
            	perror("read failed");
        	} else if (n == 0) {
            	perror("server terminated \n");
        	}
        	recv_line[n] = 0;
        	fputs(recv_line, stdout);
        	fputs("\n", stdout);
		}
	}
	// 5. 关闭 client socket
    close(sockfd);

}
